import { getServerCurrentTime } from '@/services/giftCard';
import { invertKeyValues } from '@/utils/helper.js';
import { countdownTransform, dateFormat, getDayEnd, HOURS_24 } from '@/utils/time.js';
import Taro from '@tarojs/taro';

export const ActiveStateType = {
  // 以获取, 去使用
  got: 1,
  // 领取
  draw: 2,
  // 即将开抢
  snapUp: 3,
  // 已抢光
  none: 4,
  // 明天继续
  nextTime: 5,
};

export const ActiveStateTypeInvert = invertKeyValues(ActiveStateType);

export const ActiveStateTypeText = {
  [ActiveStateType.got]: '去使用',
  [ActiveStateType.draw]: '立即领取',
  [ActiveStateType.snapUp]: '即将开抢',
  [ActiveStateType.none]: '已抢光',
  [ActiveStateType.nextTime]: '明天继续',
};

export const ProductType = {
  // 全部商品
  all: 1,
  // 指定商品
  specified: 2,
};

export const DiscountType = {
  // 满减券
  rebate: 1,
  rebateT: 2,
  // 折扣
  discount: 3,
  discountT: 4,
};

// IOS设备时间问题, 服务器返回 2000-01-01, 需要替换成 2000/01/01
export function getValidDate(str) {
  if (str === undefined || str === null) {
    throw new Error('no date input');
  }

  if (str instanceof Date) {
    return new Date(str);
  }

  if (typeof str === 'number') {
    return new Date(str);
  }

  return new Date(str.replace(/-/g, '/').replace(/T/, ' '));
}

/**
 * 每次打开小程序时, 获取服务器时间, 用于优惠券倒计时计算
 */
export async function setServerDateNowToGlobal() {
  const localNow = Date.now();

  // 获取服务器时间
  let { content: { currentTime } = {} } = await getServerCurrentTime();

  if (!currentTime) {
    // Taro.showToast({ icon: 'null', title: '获取服务器时间失败' });
    Taro.hideToast();
    console.warn('获取服务器时间失败');
    currentTime = localNow;
  }

  let serverNow = getValidDate(currentTime).getTime();
  Taro.$localDiffServerTime = serverNow - localNow;
}

/**
 * 获取时间(getTime), 已经处理了服务器的时间差
 */
export function getDateNow() {
  return Date.now() + (Taro.$localDiffServerTime ?? 0);
}

export function appendActiveState(item) {
  if (item.isReceive) {
    item.activeStateType = ActiveStateType.got;
  } else if (item.isStock === 0) {
    const startTime = getValidDate(item.startTime);
    // 未到开始时间
    if (getDateNow() < startTime) {
      // 即将开抢
      item.activeStateType = ActiveStateType.snapUp;

      // 今天内就能抢购, 加上snapUpTime
      if (getDayEnd(new Date(getDateNow())) > startTime) {
        item.snapUpTime = dateFormat(startTime, 'hh:mm');
      } else {
        item.snapUpTime = [dateFormat(startTime, 'yyyy.MM.dd'), dateFormat(startTime, 'hh:mm')];
      }
    } else {
      item.activeStateType = ActiveStateType.draw;
    }
  } else if (item.isStock === 1) {
    item.activeStateType = ActiveStateType.none;
  } else if (item.isStock === 2) {
    item.activeStateType = ActiveStateType.nextTime;
  }

  return item;
}

export function appendIsRebate(item) {
  item.isRebate = item.type === DiscountType.rebate;
  return item;
}

export const CouponStatus = {
  // 即将使用
  willUse: 'willUse',
  // 即将过期
  willExpire: 'willExpire',
  // 在使用时间范围内
  inRange: 'inRange',
  // 多少天后可用
  afterDay: 'afterDay',
  // 过期券,
  expired: 'expired',

  // 已使用
  used: 'used',
  // 未知状态
  unknown: 'unknown',
};

export const CouponType = {
  available: 0,
  used: 1,
  expired: 3,
};

export const CouponTypeInvert = invertKeyValues(CouponType);

/**
https://www.tapd.cn/58680279/prong/stories/view/1158680279001001687

1.固定时间：显示时间精确到分，显示如下
  a: 开始时间24小时内
     开始时间24小时的倒计时
  b: 开始时间24小时以上
     2021.10.29 00:00-2021.10.29 23:59
     X天后可用
  c: 距离结束 24小时以上:
     2021.10.29 00:00-2021.10.29 23:59
  d: 距离结束24小时内:
     24小时的倒计时
  e: 已经结束:
     2021.10.29 00:00-2021.10.29 23:59

2.领券后当天生效，有效时间M天，M=1 显示如下
  a: 领取即可用
     过期的24小时倒计时
  b: 已过期:
     2021.10.29可用

4.领券后X天生效，有效时间M天，M=1 显示如下
    a: 开始时间24小时内, 显示
      开始时间24小时的倒计时
    b: 开始时间24小时以上, 显示
       2021.10.28可用
    c: 距离结束24小时内:
       24小时的倒计时
    d: 已经结束:
       2021.10.28可用

3. 领券后当天生效，有效时间M天，M> 1 显示如下
    a: 距离结束 24小时以上:
       2021.10.28-2021.10.29
    b: 距离结束24小时内:
       距离结束24小时的倒计时
    c: 已经结束:
       2021.10.28-2021.10.29

5.领券后X天生效，有效时间M天，M>1 显示如下
  a: 开始时间24小时内, 显示
     开始时间24小时的倒计时
  b: 开始时间24小时以上, 显示
    2021.10.28 -2021.10.29
    X天后可用
  c: 距离结束 24小时以上:
     2021.10.28-2021.10.29
  d: 距离结束24小时内:
      24小时的倒计时
  e: 已经结束:
      2021.10.28-2021.10.29
 */

// 固定时间
// 对应规则 1
function getConstantTime({ start, end, offNow, offEnd }) {
  const timeRange = [dateFormat(start, 'yyyy.MM.dd hh:mm'), dateFormat(end, 'yyyy.MM.dd hh:mm')];

  // 开始时间 距离现在 还有 24 小时以上, 向上取整
  if (offNow > HOURS_24) {
    return {
      status: CouponStatus.afterDay,
      timeRange,
      // 向上取整
      dayDistance: Math.ceil(offNow / HOURS_24),
    };
  }

  // 开始时间 距离现在 在 24小时内
  if (offNow > 0) {
    return {
      status: CouponStatus.willUse,
      countdown: countdownTransform(offNow, 2),
    };
  }

  // 已经过期了
  if (offEnd < 0) {
    return {
      status: CouponStatus.expired,
      timeRange,
    };
  }

  // 过期还有 24小时不到了
  if (offEnd < HOURS_24) {
    return {
      status: CouponStatus.willExpire,
      countdown: countdownTransform(offEnd, 2),
    };
  }

  // 过期还有 24小时以上
  if (offEnd > HOURS_24) {
    return {
      status: CouponStatus.inRange,
      timeRange,
    };
  }

  // 未知状态
  return {
    status: CouponStatus.unknown,
    timeRange,
  };
}

// 领券后X天生效，有效时间1天
// 对应规则 2 和 4
function getDynamicOneDayTime({ start, offNow, offEnd }) {
  // a: 开始时间24小时内, 显示
  //   开始时间24小时的倒计时
  // b: 开始时间24小时以上, 显示
  //    2021.10.28可用
  // c: 距离结束24小时内:
  //    24小时的倒计时
  // d: 已经结束:
  //    2021.10.28可用

  const thatDay = dateFormat(start, 'yyyy.MM.dd');

  // 开始时间 距离现在 还有 24 小时以上, 向上取整
  if (offNow > HOURS_24) {
    return {
      status: CouponStatus.afterDay,
      thatDay,
    };
  }

  // 开始时间 距离现在 在 24小时内
  if (offNow > 0) {
    return {
      status: CouponStatus.willUse,
      countdown: countdownTransform(offNow, 2),
    };
  }

  // 已经过期了
  if (offEnd < 0) {
    return {
      status: CouponStatus.expired,
      thatDay,
    };
  }

  // 过期还有 24小时不到了
  if (offEnd < HOURS_24) {
    return {
      status: CouponStatus.willExpire,
      countdown: countdownTransform(offEnd, 2),
    };
  }

  // 未知状态
  return {
    status: CouponStatus.unknown,
    thatDay,
  };
}

// 领券后X天生效，有效时间大于1天
// 对应规则 5 和 3
function getDynamicMoreDayTime({ start, end, offNow, offEnd }) {
  const timeRange = [dateFormat(start, 'yyyy.MM.dd'), dateFormat(end, 'yyyy.MM.dd')];

  // 开始时间 距离现在 还有 24 小时以上, 向上取整
  if (offNow > HOURS_24) {
    return {
      status: CouponStatus.afterDay,
      timeRange,
      dayDistance: Math.ceil(offNow / HOURS_24),
    };
  }

  // 开始时间 距离现在 在 24小时内
  if (offNow > 0) {
    return {
      status: CouponStatus.willUse,
      countdown: countdownTransform(offNow, 2),
    };
  }

  // 已经过期了
  if (offEnd < 0) {
    return {
      status: CouponStatus.expired,
      timeRange,
    };
  }

  // 过期还有 24小时不到了
  if (offEnd < HOURS_24) {
    return {
      status: CouponStatus.willExpire,
      countdown: countdownTransform(offEnd, 2),
    };
  }

  // 过期还有 24小时以上
  if (offEnd > HOURS_24) {
    return {
      status: CouponStatus.inRange,
      timeRange,
    };
  }

  // 未知状态
  return {
    status: CouponStatus.unknown,
    timeRange,
  };
}

/**
  {
    // 优惠券状态
    status: CouponStatus,
    // 时间范围
    timeRange?: [string, string],
    // 距离天数
    dayDistance?: number,
    // 倒计时
    // [hour, minute, second, millisecond]
    countdown?: [number, number, number, number, number],
    // 某一天可用
    thatDay?: string;
  }
 * @param {object} couponInfo 优惠券详情
 * @param {CouponType} couponType 优惠券状态
 * @returns
 */
export function getCouponStatus({ startTime, endTime, timeType, totalDay }, couponType) {
  // IOS设备时间问题, 服务器返回 2000-01-01, 需要替换成 2000/01/01
  const start = getValidDate(startTime);
  const end = getValidDate(endTime);

  const now = getDateNow();

  // 固定时间
  const isConstTime = timeType === 1;

  // 已使用 和 已过期
  if (couponType !== CouponType.available) {
    const status = couponType === CouponType.used ? CouponStatus.used : CouponStatus.expired;

    // 大于1天的       2021.10.29-2021.10.30
    if (isConstTime) {
      return {
        status,
        timeRange: [dateFormat(start, 'yyyy.MM.dd hh:mm'), dateFormat(end, 'yyyy.MM.dd hh:mm')],
      };
    }

    // 1天的         2021.10.29
    if (totalDay === 1) {
      return {
        status,
        thatDay: dateFormat(start, 'yyyy.MM.dd'),
      };
    }

    // 固定时间       2021.10.29 00:00-2021.10.29 23:59
    return {
      status,
      timeRange: [dateFormat(start, 'yyyy.MM.dd'), dateFormat(end, 'yyyy.MM.dd')],
    };
  }

  const offNow = start.getTime() - now;
  const offEnd = end.getTime() - now;

  // 可使用

  // 固定时间
  if (isConstTime) {
    return getConstantTime({ start, end, offNow, offEnd });
  }

  // 大于1天的
  if (totalDay === 1) {
    return getDynamicOneDayTime({ start, end, offNow, offEnd });
  }

  return getDynamicMoreDayTime({ start, end, offNow, offEnd });
}

export function addMyCouponExtraAttr(item, couponType) {
  return {
    ...appendIsRebate(item),
    couponStatus: getCouponStatus(item, couponType),
  };
}

export function addCouponListExtraAttr(item) {
  return appendActiveState({
    ...appendIsRebate({ ...item }),
  });
}

// 选中 最大优惠
export function setMaxRealityDiscountAmountSelected(arr, arrPlat) {
  let maxIndex = -1,
    maxPlatIndex = -1,
    maxPlatConIndex = -1;
  let maxValue = -1,
    maxPlatValue = -1,
    maxPlatConValue = -1;

  arr.length > 0 &&
    arr.forEach((item, index) => {
      const { realityDiscountAmount } = item;
      item.selected = 2;
      if (realityDiscountAmount > maxValue) {
        maxValue = realityDiscountAmount;
        maxIndex = index;
      }
    });

  arrPlat.length > 0 &&
    arrPlat.forEach((item, index) => {
      const { realityDiscountAmount, activityType } = item;
      item.selected = 2;
      if (realityDiscountAmount > maxPlatValue) {
        maxPlatValue = realityDiscountAmount;
        maxPlatIndex = index;
      }
      if (activityType.indexOf('2') >= 0 && realityDiscountAmount > maxPlatConValue) {
        maxPlatConValue = realityDiscountAmount;
        maxPlatConIndex = index;
      }
    });

  if (maxIndex != -1 && maxPlatIndex == -1) {
    arr[maxIndex].selected = 1;
  } else if (maxIndex == -1 && maxPlatIndex != -1) {
    arrPlat[maxPlatIndex].selected = 1;
  } else if (maxIndex != -1 && maxPlatIndex != -1 && maxPlatConIndex == -1) {
    maxValue >= maxPlatValue ? (arr[maxIndex].selected = 1) : (arrPlat[maxPlatIndex].selected = 1);
  } else if (maxIndex != -1 && maxPlatIndex != -1 && maxPlatConIndex != -1) {
    maxValue + maxPlatConValue >= maxPlatValue
      ? ((arr[maxIndex].selected = 1), (arrPlat[maxPlatConIndex].selected = 1))
      : (arrPlat[maxPlatIndex].selected = 1);
  }

  return { arr, arrPlat };
}

export function getUsableSelectedCouponList(arr) {
  const selectedCouponList = arr?.filter(({ selected }) => {
    return selected === 1;
  });

  const discountAmount = selectedCouponList?.reduce((sum, { realityDiscountAmount }) => {
    sum += realityDiscountAmount ?? 0;
    return sum;
  }, 0);

  return { selectedCouponList, discountAmount };
}

export function getOrderCouponPayload(orderDetail, sourceType) {
  // TODO: 加入orgId, 这边的逻辑按照 merchantId 进行 group 失效, 暂时不处理
  const orgId = orderDetail?.productCarConfirmOrgResponsesList?.[0]?.orgId;

  // 获取所有的 商品
  const productInfoList =
    orderDetail.productCarConfirmOrgResponsesList &&
    orderDetail.productCarConfirmOrgResponsesList.length > 0
      ? orderDetail.productCarConfirmOrgResponsesList
          .map((item) => {
            return item.productCarConfirmInfoList;
          })
          .flat()
      : [];

  const products =
    productInfoList.length > 0
      ? productInfoList.map((pro) => {
          let { productVariantReleaseId, favouredType, productIndustryId, activityPrice, price } =
            pro;
          return {
            productIndustryId,
            variantId: productVariantReleaseId,
            totalPrice: activityPrice === undefined ? price : activityPrice,
            isActivity: favouredType ? 1 : 0,
          };
        })
      : [];

  // 每个 merchantId 计算 variantId 和 totalPrice
  const payload = {
    sourceType,
    orgId,
    products,
  };

  return payload;
}

export function resetSelectedStatus(usableCouponList = []) {
  return usableCouponList.map((item) => {
    item.selected = 2;
    return item;
  });
}
